package cn.harry.common.exception;

import cn.harry.common.api.R;
import cn.harry.common.api.ResultCode;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.security.authorization.AuthorizationDeniedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

/**
 * 异常处理器
 *
 * @author harry
 * @公众号 Harry技术
 */
@Slf4j
@RestControllerAdvice
public class ApiExceptionHandler {

    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public <T> R<T> noHandlerFoundException(NoHandlerFoundException e) {
        log.error("请求路径错误 抛出:", e);
        return R.failed(ResultCode.NOT_FOUND);
    }

    @ExceptionHandler(AuthorizationDeniedException.class)
    @ResponseStatus(HttpStatus.FORBIDDEN)
    public <T> R<T> handleAuthorizationDeniedException(AuthorizationDeniedException e) {
        log.error("权限不足 抛出:", e);
        return R.failed(ResultCode.FORBIDDEN);
    }

    @ExceptionHandler(BadSqlGrammarException.class)
    @ResponseStatus(HttpStatus.FORBIDDEN)
    public <T> R<T> handleBadSqlGrammarException(BadSqlGrammarException e) {
        log.error(e.getMessage(), e);
        String errorMsg = e.getMessage();
        if (StrUtil.isNotBlank(errorMsg) && errorMsg.contains("denied to user")) {
            return R.failed(ResultCode.FORBIDDEN_OPERATION);
        } else {
            return R.failed(e.getMessage());
        }
    }

    /**
     * 处理自定义异常
     */
    @ExceptionHandler(ApiException.class)
    public <T> R<T> handleApiException(ApiException e) {
        log.error("自定义ApiException 抛出:", e);
        return R.failed(e.getCode(), e.getMsg());
    }

    @ExceptionHandler(Exception.class)
    public <T> R<T> handleException(Exception e) {
        log.error(e.getMessage(), e);
        return R.failed();
    }

}
